package com.culture.java.online.education.platform.common.web.exception.handler;

import com.culture.java.online.education.platform.common.base.exception.CustomServiceException;
import com.culture.java.online.education.platform.common.base.response.Code;
import com.culture.java.online.education.platform.common.base.response.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

// 全局异常处理器
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public R exceptionHandler(Exception e) {
        log.error("[GlobalExceptionHandler.exceptionHandler] 全局异常被触发", e);
        return R.failure(Code.FAILURE);
    }

    @ExceptionHandler(CustomServiceException.class)
    public R customServiceExceptionHandler(CustomServiceException e) {
        System.out.println("GlobalExceptionHandler.customServiceExceptionHandler");
        e.printStackTrace();
        return R.failure(e.getCode());
    }

    // 实体类属性参数校验异常处理
    @ExceptionHandler(BindException.class)
    public R bindExceptionHandler(BindException e) {
        List<ObjectError> errorList = e.getAllErrors();
        List<String> messageList = new ArrayList<>();
        for (ObjectError objectError : errorList) {
            String defaultMessage = objectError.getDefaultMessage();
            messageList.add(defaultMessage);
        }
        return R.failure(Code.PARAM_VALID_ERROR, messageList);
    }

    // 控制层接口方法形参校验异常处理
    @ExceptionHandler(ConstraintViolationException.class)
    public R constraintViolationExceptionHandler(ConstraintViolationException e) {
        Set<ConstraintViolation<?>> constraintViolationSet = e.getConstraintViolations();
        Set<String> messageSet = new HashSet<>();
        for (ConstraintViolation<?> constraintViolation : constraintViolationSet) {
            String message = constraintViolation.getMessage();
            messageSet.add(message);
        }
        return R.failure(Code.PARAM_VALID_ERROR, messageSet);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        List<ObjectError> errorList = bindingResult.getAllErrors();
        List<String> messageList = new ArrayList<>();
        for (ObjectError objectError : errorList) {
            String defaultMessage = objectError.getDefaultMessage();
            messageList.add(defaultMessage);
        }
        return R.failure(Code.PARAM_VALID_ERROR, messageList);
    }

}
